package com.huffman.smart_picture.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huffman.smart_picture.common.exception.BusinessException;
import com.huffman.smart_picture.common.exception.ErrorEnum;
import com.huffman.smart_picture.domain.constants.CommonConstant;
import com.huffman.smart_picture.domain.constants.RedisConstant;
import com.huffman.smart_picture.domain.entity.User;
import com.huffman.smart_picture.domain.enums.PlatformEnum;
import com.huffman.smart_picture.domain.request.user.UserLoginRequest;
import com.huffman.smart_picture.domain.request.user.UserRegisterRequest;
import com.huffman.smart_picture.domain.vo.manage.DashboardUserRatioVo;
import com.huffman.smart_picture.domain.vo.user.UserVo;
import com.huffman.smart_picture.mapper.UserMapper;
import com.huffman.smart_picture.service.SpaceUserService;
import com.huffman.smart_picture.service.UserService;
import com.huffman.smart_picture.utils.RegexUtils;
import com.huffman.smart_picture.utils.ThrowUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @author DengLin
 * @description 针对表【user】的数据库操作Service实现
 * @createDate 2024-06-27 16:52:38
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SpaceUserService spaceUserService;

    @Override
    public void register(UserRegisterRequest userRegisterRequest) {
        String email = userRegisterRequest.getEmail();
        String username = userRegisterRequest.getUsername();
        String password = userRegisterRequest.getPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        String emailCode = userRegisterRequest.getEmailCode();

        ThrowUtil.throwIf(username.length() > 8, ErrorEnum.PARAM_ILLICIT, "账户过长");
        ThrowUtil.throwIf(password.length() > 16, ErrorEnum.PARAM_ILLICIT, "密码过长");
        ThrowUtil.throwIf(checkPassword.length() > 16, ErrorEnum.PARAM_ILLICIT, "密码过长");
        ThrowUtil.throwIf(!RegexUtils.matches(RegexUtils.REGEX_EMAIL, email), ErrorEnum.PARAM_ILLICIT, "邮箱格式错误");

        // 验证码验证
        String cacheKey = RedisConstant.REGISTER_CHECK_CODE + ":" + email;
        String redisCode = stringRedisTemplate.opsForValue().getAndDelete(cacheKey);
        ThrowUtil.throwIf(!StringUtils.hasText(redisCode), ErrorEnum.RESOURCE_NOT_FIND, "验证码过期");
        ThrowUtil.throwIf(!redisCode.equals(emailCode), ErrorEnum.PARAM_CHECK_MISTAKE, "验证码错误");


        if (!checkPassword.equals(password)) {
            throw new BusinessException(ErrorEnum.PARAM_CHECK_MISTAKE, "密码不一致");
        }


        password = encryptPassword(password);

        synchronized (username.intern()) {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getUsername, username).or().eq(User::getEmail, email);
            if (count(queryWrapper) > 0) {
                throw new BusinessException(ErrorEnum.USER_REGISTER_FAIL, "该账号或邮箱已存在");
            }
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            user.setRole(CommonConstant.USER);
            user.setNickname("新用户");
            user.setEmail(email);
            user.setAvatar("https://s1.locimg.com/2025/04/03/2099e58aca0f7.webp");
            save(user);
        }

    }

    @Override
    public UserVo login(UserLoginRequest userLoginRequest) {
        // 校验数据
        String username = userLoginRequest.getUsername();
        String password = userLoginRequest.getPassword();
        Integer platform = userLoginRequest.getPlatform();

        String encryptPassword = encryptPassword(password);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = getOne(queryWrapper);

        if (Objects.isNull(user)) {
            throw new BusinessException(ErrorEnum.USER_LOGIN_FAIL, "账户不存在");
        }

        if (!encryptPassword.equals(user.getPassword())) {
            throw new BusinessException(ErrorEnum.USER_LOGIN_FAIL, "密码错误");
        }

        // 验证管理端
        if (PlatformEnum.ADMIN_PLATFORM.getPlatformCode().equals(platform)) {
            ThrowUtil.throwIf(!CommonConstant.ADMIN.equals(user.getRole()), ErrorEnum.NO_AUTH, "权限不足");
        }

        // 查询空间角色
        Map<Long, Integer> spaceUserRoleMap = spaceUserService.getSpaceUserRole(user.getId());
        UserVo userVo = UserVo.convert(user);
        long nowTime = new Date().getTime();
        long expireTime = nowTime + CommonConstant.ONE_DAY * 30;
        userVo.setExpireTime(expireTime);
        userVo.setSpaceUserRoleMap(spaceUserRoleMap);
        return userVo;
    }

    @Override
    public String encryptPassword(String password) {
        return DigestUtils.md5DigestAsHex((CommonConstant.SALT + password).getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public boolean banUser(Long id) {
        ThrowUtil.throwIf(id == null || id < 0, ErrorEnum.PARAM_ILLICIT, "用户id不存在");
        User user = getById(id);
        ThrowUtil.throwIf(user == null, ErrorEnum.RESOURCE_NOT_FIND, "用户不存在");
        ThrowUtil.throwIf(Objects.equals(user.getStatus(), CommonConstant.BAN), ErrorEnum.REQUEST_MANY, "用户已被封禁");
        user.setStatus(CommonConstant.BAN);
        return updateById(user);
    }

    @Override
    public boolean unbanUser(Long id) {
        ThrowUtil.throwIf(id == null || id < 0, ErrorEnum.PARAM_ILLICIT, "用户id不存在");
        User user = getById(id);
        ThrowUtil.throwIf(user == null, ErrorEnum.RESOURCE_NOT_FIND, "用户不存在");
        ThrowUtil.throwIf(Objects.equals(user.getStatus(), CommonConstant.UNBAN), ErrorEnum.REQUEST_MANY, "用户状态正常");
        user.setStatus(CommonConstant.UNBAN);
        return updateById(user);
    }

    @Override
    public DashboardUserRatioVo vipAndNonVipCount() {
        return this.baseMapper.vipAndNonVipCount();
    }

}




